"""
深度诊断语音文件问题
找出为什么 ffmpeg 无法读取
"""

import os
import wave
import struct
from pathlib import Path

def hex_dump(data, length=64):
    """十六进制转储前 N 字节"""
    return ' '.join(f'{b:02x}' for b in data[:length])

def analyze_wav_file(file_path):
    """深度分析 WAV 文件结构"""
    print("="*70)
    print(f"🔍 分析文件: {file_path}")
    print("="*70)
    
    file_path = Path(file_path)
    
    # 基本信息
    if not file_path.exists():
        print("❌ 文件不存在!")
        return
    
    file_size = os.path.getsize(file_path)
    print(f"\n📊 基本信息:")
    print(f"   文件大小: {file_size:,} bytes")
    
    if file_size == 0:
        print("   ❌ 文件为空!")
        return
    
    # 读取文件头
    with open(file_path, 'rb') as f:
        header = f.read(min(512, file_size))
    
    print(f"   前 64 字节 (hex): {hex_dump(header)}")
    
    # 检查 WAV 文件头
    print(f"\n🔍 WAV 文件头检查:")
    
    if len(header) < 44:
        print(f"   ❌ 文件太小 (< 44 bytes),不是有效的 WAV 文件")
        print(f"   实际大小: {len(header)} bytes")
        return
    
    # RIFF 标识
    riff = header[0:4]
    print(f"   RIFF 标识: {riff} ({riff.decode('ascii', errors='ignore')})")
    if riff != b'RIFF':
        print(f"   ❌ 不是 RIFF 格式! 应该是 'RIFF'")
        print(f"   这可能是:")
        print(f"      - 损坏的文件")
        print(f"      - API 返回的错误消息")
        print(f"      - 非 WAV 格式")
        
        # 尝试解析为文本
        try:
            text_content = header.decode('utf-8', errors='ignore')
            if 'error' in text_content.lower() or 'exception' in text_content.lower():
                print(f"\n   ⚠️  文件内容看起来像错误消息:")
                print(f"   {text_content[:200]}")
        except:
            pass
        return
    
    # 文件大小
    chunk_size = struct.unpack('<I', header[4:8])[0]
    print(f"   RIFF Chunk Size: {chunk_size:,} bytes")
    expected_size = chunk_size + 8
    print(f"   预期文件大小: {expected_size:,} bytes")
    
    if abs(expected_size - file_size) > 100:
        print(f"   ⚠️  文件大小不匹配! 差异: {abs(expected_size - file_size)} bytes")
    
    # WAVE 标识
    wave_id = header[8:12]
    print(f"   WAVE 标识: {wave_id} ({wave_id.decode('ascii', errors='ignore')})")
    if wave_id != b'WAVE':
        print(f"   ❌ 不是 WAVE 格式!")
        return
    
    # fmt chunk
    fmt_id = header[12:16]
    print(f"   fmt 标识: {fmt_id} ({fmt_id.decode('ascii', errors='ignore')})")
    if fmt_id != b'fmt ':
        print(f"   ❌ 缺少 fmt chunk!")
        return
    
    fmt_size = struct.unpack('<I', header[16:20])[0]
    print(f"   fmt Chunk Size: {fmt_size} bytes")
    
    # 音频格式
    audio_format = struct.unpack('<H', header[20:22])[0]
    print(f"   音频格式: {audio_format} ({'PCM' if audio_format == 1 else '未知'})")
    
    num_channels = struct.unpack('<H', header[22:24])[0]
    print(f"   声道数: {num_channels}")
    
    sample_rate = struct.unpack('<I', header[24:28])[0]
    print(f"   采样率: {sample_rate} Hz")
    
    byte_rate = struct.unpack('<I', header[28:32])[0]
    print(f"   字节率: {byte_rate:,} bytes/sec")
    
    block_align = struct.unpack('<H', header[32:34])[0]
    print(f"   块对齐: {block_align} bytes")
    
    bits_per_sample = struct.unpack('<H', header[34:36])[0]
    print(f"   位深度: {bits_per_sample} bits")
    
    # 查找 data chunk
    print(f"\n🔍 数据 Chunk 检查:")
    data_found = False
    pos = 36
    
    while pos < len(header) - 8:
        chunk_id = header[pos:pos+4]
        chunk_size = struct.unpack('<I', header[pos+4:pos+8])[0]
        
        print(f"   Chunk: {chunk_id} ({chunk_id.decode('ascii', errors='ignore')}) Size: {chunk_size:,} bytes")
        
        if chunk_id == b'data':
            data_found = True
            print(f"   ✅ 找到 data chunk!")
            print(f"   数据大小: {chunk_size:,} bytes")
            
            # 计算音频时长
            if byte_rate > 0:
                duration = chunk_size / byte_rate
                print(f"   预计时长: {duration:.2f} 秒")
            
            break
        
        pos += 8 + chunk_size
    
    if not data_found:
        print(f"   ❌ 未找到 data chunk!")
    
    # 使用 wave 模块验证
    print(f"\n🔍 Python wave 模块验证:")
    try:
        with wave.open(str(file_path), 'rb') as wav:
            print(f"   ✅ 可以打开")
            print(f"   声道: {wav.getnchannels()}")
            print(f"   采样宽度: {wav.getsampwidth()} bytes")
            print(f"   采样率: {wav.getframerate()} Hz")
            print(f"   帧数: {wav.getnframes():,}")
            print(f"   时长: {wav.getnframes() / wav.getframerate():.2f} 秒")
    except Exception as e:
        print(f"   ❌ 无法打开: {e}")
    
    # 尝试用 moviepy 读取
    print(f"\n🔍 MoviePy 读取测试:")
    try:
        from moviepy.editor import AudioFileClip
        audio = AudioFileClip(str(file_path))
        print(f"   ✅ MoviePy 可以读取")
        print(f"   时长: {audio.duration:.2f} 秒")
        audio.close()
    except Exception as e:
        print(f"   ❌ MoviePy 失败: {e}")
        print(f"\n   这就是视频合成失败的原因!")

def compare_all_speech_files(speech_dir):
    """比较所有语音文件"""
    speech_path = Path(speech_dir)
    
    if not speech_path.exists():
        print(f"❌ 目录不存在: {speech_dir}")
        return
    
    wav_files = sorted(speech_path.glob("p*.wav"))
    
    if not wav_files:
        print("❌ 没有找到 WAV 文件")
        return
    
    print("\n" + "="*70)
    print("📊 批量对比所有语音文件")
    print("="*70)
    print()
    
    for wav_file in wav_files:
        size = os.path.getsize(wav_file)
        
        # 快速检查
        try:
            with wave.open(str(wav_file), 'rb') as wav:
                frames = wav.getnframes()
                rate = wav.getframerate()
                duration = frames / rate if rate > 0 else 0
                status = "✅" if frames > 0 else "❌"
        except:
            status = "❌"
            duration = 0
        
        print(f"{status} {wav_file.name:12} - {size:>10,} bytes - {duration:>6.2f} 秒")
    
    print()

if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1:
        # 分析指定文件
        analyze_wav_file(sys.argv[1])
    else:
        # 分析默认目录
        speech_dir = "generated_stories/example/speech"
        
        print("="*70)
        print("🎙️ 语音文件诊断工具")
        print("="*70)
        print()
        
        # 先对比所有文件
        compare_all_speech_files(speech_dir)
        
        # 然后详细分析问题文件
        problem_file = Path(speech_dir) / "p2.wav"
        if problem_file.exists():
            analyze_wav_file(problem_file)
        
        print("\n" + "="*70)
        print("💡 使用方法:")
        print("="*70)
        print("  分析特定文件:")
        print("    python diagnose_audio_file.py generated_stories/example/speech/p2.wav")
        print()
